/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// #include <cstdio>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include "bts_le_gap.h"
#include "bts_gatt_server.h"

#ifdef ADAPTER_BT_L0_SUPPORT
#include "iotc_ble_def.h"
#include "ohos_bt_log.h"
#else
#include "log.h"
#endif

#include "ohos_bt_gap.h"

uint8_t g_server_id = 0;  /* gatt server ID */
static uint8_t g_descVal[]  = {0x55, 0x66, 0x77, 0x88};
static uint8_t g_charaVal[] = {0x11, 0x22, 0x33, 0x44};

static int g_deleteServiceHandle = 0;
static uint16_t g_serverRequestId = 0;

#define MAX_READ_REQ_LEN 200

static uint16_t g_srvc_handle = 0;
static BleGattServiceWrite g_srvc_func_write;
static BleGattServiceRead g_srvc_func_read;
static BleGattServiceWrite g_srvc_func_descript;
static BtUuid g_srvc_write_uuid;
static BtUuid g_srvc_read_uuid;

static uint16_t g_cb_chara_handle = 0;
static uint16_t g_cb_desc_handle = 0;
static uint16_t g_indicate_handle = 0;
static char g_hilink_cccd_uuid[2] = {0x29,0x02};


static uint32_t Convert_To_Permissions(uint32_t permissions)
{
    uint32_t perm = 0;
    if (permissions & OHOS_GATT_PERMISSION_READ) {
        perm |= GATT_ATTRIBUTE_PERMISSION_READ;
    }
    if (permissions & OHOS_GATT_PERMISSION_READ_ENCRYPTED) {
        perm |= (GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_ENCRYPTION_NEED);
    }
    if (permissions & OHOS_GATT_PERMISSION_READ_ENCRYPTED_MITM) {
        perm |= (GATT_ATTRIBUTE_PERMISSION_READ |
            GATT_ATTRIBUTE_PERMISSION_ENCRYPTION_NEED | GATT_ATTRIBUTE_PERMISSION_MITM_NEED);
    }
    if (permissions & OHOS_GATT_PERMISSION_WRITE) {
        perm |= GATT_ATTRIBUTE_PERMISSION_WRITE;
    }
    if (permissions & OHOS_GATT_PERMISSION_WRITE_ENCRYPTED) {
        perm |= (GATT_ATTRIBUTE_PERMISSION_WRITE | GATT_ATTRIBUTE_PERMISSION_ENCRYPTION_NEED);
    }
    if (permissions & OHOS_GATT_PERMISSION_WRITE_ENCRYPTED_MITM) {
        perm |= (GATT_ATTRIBUTE_PERMISSION_WRITE |
            GATT_ATTRIBUTE_PERMISSION_ENCRYPTION_NEED | GATT_ATTRIBUTE_PERMISSION_MITM_NEED);
    }
    return perm;
}


static void print_bt_uuid(bt_uuid_t *uuid) {
    printf("print bt_uuid_t uuid_len: %d,uuid:", uuid->uuid_len);
    for (int8_t i = 0; i < uuid->uuid_len; i++) {
        printf("%02x", (uint8_t)uuid->uuid[i]);
    }
    printf("\n");
}

char *hexToString(uint8_t *data, int len) {
    char *str = (char *)malloc(len * 2 + 1);
    int index = 0;

    for (int k = len-1; k >= 0; k--) {
        sprintf(&str[index], "%02x", data[k]);
        index += 2;
    }

    str[index] = '\0';
    return str;
}

int convertBtUuid(BtUuid *btUuid, uint8_t *uuid) {
    btUuid->uuidLen = OHOS_BLE_UUID_MAX_LEN;
    btUuid->uuid = (uint8_t *)IotcMalloc(OHOS_BLE_UUID_MAX_LEN * sizeof(uint8_t));
    if (btUuid->uuid == NULL) {
      LOG_PRINT("malloc failed");
      return -1;
    }

    memcpy_s(btUuid->uuid, btUuid->uuidLen, uuid, OHOS_BLE_UUID_MAX_LEN);
    // LOG_PRINT("convertBtUuid uuidLen:%d uuid:%s", btUuid->uuidLen, hexToString(btUuid->uuid,btUuid->uuidLen));
    return 0;
}


int BleGattsStartServiceEx(int *srvcHandle, BleGattService *srvcInfo) {
    LOG_PRINT( "[iot_ble_lite_log] BleGattsStartServiceEx srvcHandle:%u srvcInfo.attrNum:%d ",srvcHandle,srvcInfo->attrNum);

    errcode_t ret = ERRCODE_BT_SUCCESS;
    BtUuid btUuid;
    
    if (srvcInfo->attrNum > 1) {
      BleGattAttr *attr = &(srvcInfo->attrList[0]);
      ret = convertBtUuid(&btUuid, attr->uuid);
      if(ret < 0) {
        LOG_PRINT("[bluetooth]convertBtUuid failed %d",ret);
        return ret;
      }
    }

    ret = BleGattsRegister(btUuid);
    if (ret != ERRCODE_BT_SUCCESS) {
      LOG_PRINT("[bluetooth] BleGattsRegister failed");
      return ret;
    }

    for (unsigned int i = 0; i < srvcInfo->attrNum; i++) {
        BleGattAttr *attr = &(srvcInfo->attrList[i]);
        ret = convertBtUuid(&btUuid, attr->uuid);
        if(ret < 0) {
           LOG_PRINT("[bluetooth] convertBtUuid failed %d",ret);
           continue;
        }
        switch (attr->attrType) {
            case OHOS_BLE_ATTRIB_TYPE_SERVICE:
                ret = BleGattsAddService(g_server_id, btUuid, 1, srvcInfo->attrNum);
                LOG_PRINT( "[bluetooth] BleGattsAddService ret:%d",ret);
                break;
            case OHOS_BLE_ATTRIB_TYPE_CHAR:
                ret = BleGattsAddCharacteristic(g_server_id, g_srvc_handle, btUuid, attr->properties, attr->permission);
                if (ret != ERRCODE_BT_SUCCESS) {
                     LOG_PRINT( "[bluetooth] BleGattsAddCharacteristic ret:%d  properties:%d",ret, attr->properties);
                }
                if((attr->properties & IOTC_BLE_GATT_CHARACTER_PROPERTY_BIT_WRITE) == IOTC_BLE_GATT_CHARACTER_PROPERTY_BIT_WRITE) {
                    if (attr->func.write) {
                        g_srvc_write_uuid = btUuid;
                        g_srvc_func_write = attr->func.write;
                    }
                }else if((attr->properties & IOTC_BLE_GATT_CHARACTER_PROPERTY_BIT_READ) == IOTC_BLE_GATT_CHARACTER_PROPERTY_BIT_READ) {
                    if (attr->func.read) {
                        g_srvc_read_uuid = btUuid;
                        g_srvc_func_read = attr->func.read;
                    }
                }
                break;
            case OHOS_BLE_ATTRIB_TYPE_CHAR_VALUE:
                    break;
            case OHOS_BLE_ATTRIB_TYPE_CHAR_CLIENT_CONFIG:
                break;
            case OHOS_BLE_ATTRIB_TYPE_CHAR_USER_DESCR:
                ret = BleGattsAddDescriptor(g_server_id, g_srvc_handle, btUuid, attr->permission);
                if (ret != ERRCODE_BT_SUCCESS) {
                    LOG_PRINT("[bluetooth] BleGattsAddDescriptor failed:%x.",  ret);
                }
                break;
            default:
                LOG_PRINT("[bluetooth] Unknown ");
        }

        if ((attr->properties & OHOS_GATT_CHARACTER_PROPERTY_BIT_INDICATE) ||
            (attr->properties & OHOS_GATT_CHARACTER_PROPERTY_BIT_NOTIFY)) {
            g_indicate_handle = g_cb_chara_handle;
            LOG_PRINT("[bluetooth] g_indicate_handle :%d.",  g_indicate_handle);
            BtUuid bt_uuid_des = {0};
            bt_uuid_des.uuid = g_hilink_cccd_uuid;
            bt_uuid_des.uuidLen = sizeof(g_hilink_cccd_uuid);
            ret = BleGattsAddDescriptor(g_server_id, g_srvc_handle,
                bt_uuid_des, OHOS_GATT_PERMISSION_READ | OHOS_GATT_PERMISSION_WRITE);
            if (ret != ERRCODE_BT_SUCCESS) {
                LOG_PRINT("[bluetooth] BleGattsAddDescriptor failed:%d.",  ret);
            }
            if (ret == ERRCODE_BT_SUCCESS) {
                 if (attr->func.write) {
                    g_srvc_func_descript = attr->func.write;
                 }
            }
        }
    }
    if (ret != ERRCODE_BT_SUCCESS) {
        LOG_PRINT("[bluetooth] BleGattsStartServiceEx for failed:%d.",  ret);
    }
    ret = BleGattsStartService(g_server_id, g_srvc_handle);
    if (ret != ERRCODE_BT_SUCCESS) {
        LOG_PRINT("[bluetooth] BleGattsStartService error ret:%d.",  ret);
    }
    return ret;
}

int BleGattsStopServiceEx(int srvcHandle) {
  LOG_PRINT("[bluetooth] BleGattsStopServiceEx");
  return BleGattsStopService(0, srvcHandle);
}


int BleGattsRegister(BtUuid appUuid)
{
    LOG_PRINT("[bluetooth] BleGattsRegister");
    bt_uuid_t uuid = {0};

   // HILOG_DEBUG(0, "[bluetooth] BleGattsRegister uuidLen:%d uuid:%s", appUuid.uuidLen,  hexToString(&appUuid.uuid,appUuid.uuidLen));

    uuid.uuid_len = appUuid.uuidLen;
    (void)memcpy_s(uuid.uuid, appUuid.uuidLen, (uint8_t *)appUuid.uuid, appUuid.uuidLen);
    // print_bt_uuid(&uuid);
    uint8_t ret = gatts_register_server(&uuid, &g_server_id);
    if (ret != ERRCODE_BT_SUCCESS) {
        HILOG_DEBUG("[bluetooth] gatts_register_server error:%d", ret);
        return ret;
    }
    HILOG_DEBUG("[bluetooth] gatts_register_server  g_server_id:%u", g_server_id);
    if (g_bleGattsCb->registerServerCb) {
        g_bleGattsCb->registerServerCb(0, g_server_id, &appUuid);
    }
    return ret;
}

int BleGattsUnRegister(int serverId)
{
    HILOG_DEBUG("[bluetooth] BleGattsUnRegister");
    return gatts_unregister_server(serverId);
}

int BleGattsAddService(int serverId, BtUuid srvcUuid, bool isPrimary, int number)
{
    HILOG_DEBUG("[bluetooth] BleGattsAddService :%d", serverId);
    bt_uuid_t uuid = {0};
    uuid.uuid_len = srvcUuid.uuidLen;
    (void)memcpy_s(uuid.uuid, srvcUuid.uuidLen, (uint8_t *)srvcUuid.uuid, srvcUuid.uuidLen);

    return gatts_add_service(serverId, &uuid, isPrimary);
}

int BleGattsAddCharacteristic(int serverId, int srvcHandle, BtUuid characUuid,
                              int properties, int permissions)
{
    LOG_PRINT("[bluetooth] BleGattsAddCharacteristic callback in serverId:%d", serverId);
   // LOG_PRINT("BleGattsAddCharacteristic characUuid:%s", hexToString(characUuid.uuid, characUuid.uuidLen));

    bt_uuid_t uuid = {0};
    gatts_add_chara_info_t charaInfo = {0};

    uuid.uuid_len = characUuid.uuidLen;
    (void)memcpy_s(uuid.uuid, characUuid.uuidLen, (uint8_t *)characUuid.uuid, characUuid.uuidLen);

    charaInfo.chara_uuid   = uuid;
    charaInfo.properties   = properties;
    charaInfo.permissions  = Convert_To_Permissions(permissions);
    charaInfo.value_len    = sizeof(g_charaVal);
    charaInfo.value        = g_charaVal;

    gatts_add_character_result_t chara_result = {0};
    int ret =  gatts_add_characteristic_sync(serverId, srvcHandle, &charaInfo,&chara_result);
    if (ret != ERRCODE_BT_SUCCESS) {
        LOG_PRINT("BleGattsAddCharacteristic ret:%d handle:%d, g_cb_chara_handle=value_handle:%d.", ret, chara_result.handle, chara_result.value_handle);
        return ret;
    }
    g_cb_chara_handle = chara_result.value_handle;
    return ret;
}

int BleGattsAddDescriptor(int serverId, int srvcHandle, BtUuid descUuid, int permissions)
{
    HILOG_DEBUG("[bluetooth] BleGattsAddDescriptor serverId %d", serverId);
    bt_uuid_t uuid = {0};
    gatts_add_desc_info_t descriptor = {0};
    uint16_t desc_handle = 0;
    uuid.uuid_len = descUuid.uuidLen;
    (void)memcpy_s(uuid.uuid, descUuid.uuidLen, (uint8_t *)descUuid.uuid, descUuid.uuidLen);
    //LOG_PRINT("BleGattsAddDescriptor uuid:%s", hexToString(uuid.uuid, uuid.uuid_len));

    descriptor.desc_uuid    = uuid;
    descriptor.permissions  = Convert_To_Permissions(permissions);
    descriptor.value_len    = sizeof(g_descVal);
    descriptor.value        = g_descVal;
    int ret = gatts_add_descriptor_sync(g_server_id, srvcHandle, &descriptor, &desc_handle);
    if (ret != ERRCODE_BT_SUCCESS) {
        HILOG_DEBUG("[bluetooth] BleGattsAddDescriptor srvcHandle:%u  ret:%d desc_handle:%d. per:%08x ", srvcHandle, ret, desc_handle, descriptor.permissions);
        return ret;
    }
    g_cb_desc_handle = desc_handle;
    return ret;
}

int BleGattsStartService(int serverId, int srvcHandle)
{
    HILOG_DEBUG("[bluetooth] BleGattsStartService serverId= %d ", serverId);
    return gatts_start_service(serverId, srvcHandle);
}

int BleGattsStopService(int serverId, int srvcHandle)
{
    HILOG_DEBUG("[bluetooth] BleGattsStopService serverId= %d ", serverId);
    return gatts_stop_service(serverId, srvcHandle);
}

int BleGattsDeleteService(int serverId, int srvcHandle)
{   
    HILOG_DEBUG("[bluetooth] BleGattsDeleteService serverId:%d ", serverId);
    int ret = 0;
    if (g_server_id == 0) {
        return ret;
    }
    g_deleteServiceHandle = g_srvc_handle;
    ret = gatts_delete_all_services(g_server_id);
    if (ret == 0) {
        HILOG_DEBUG("[bluetooth] gatts_delete_all_services serverId:%d ret:%d", g_server_id, ret);
        g_server_id = 0;
    }
    return ret;
}

int BleGattsSendResponse(int serverId, GattsSendRspParam *param)
{   
    HILOG_DEBUG("[bluetooth] BleGattsSendResponse serverId:%d ", serverId);
    gatts_send_rsp_t rspParam = {0};

    rspParam.request_id = g_serverRequestId;
    rspParam.status = 0;
    rspParam.offset = 0;
    rspParam.value_len = param->valueLen;
    rspParam.value = (uint8_t *)param->value;

    int ret = gatts_send_response(serverId, param->connectId, &rspParam);
    if (ret != ERRCODE_BT_SUCCESS) {
        HILOG_DEBUG("BleGattsSendResponse send write resp, ret:%x.", ret);
        return ret;
    }
    return ret;
}

int BleGattsSendIndication(int serverId, GattsSendIndParam *param)
{
    errcode_t ret = ERRCODE_BT_FAIL;
    gatts_ntf_ind_t ntfParam = {0};

    HILOG_DEBUG("[bluetooth] BleGattsSendIndication serverId:%d", serverId);

    // ntfParam.attr_handle   = param->attrHandle;
    ntfParam.value_len     = param->valueLen;
    ntfParam.value         = (uint8_t *)param->value;
    ntfParam.attr_handle   = g_indicate_handle;

    ret = gatts_notify_indicate(g_server_id, param->connectId, &ntfParam);
    if (ret != ERRCODE_BT_SUCCESS) {
        HILOG_DEBUG("[bluetooth] gatts_notify_indicate ret:%d -> %X", ret, ret);
        return ret;
    }
    if (g_srvc_func_descript) {
        int ret = g_srvc_func_descript(ntfParam.value,ntfParam.value_len);
        if (ret != ERRCODE_BT_SUCCESS) {
            HILOG_DEBUG("g_srvc_func_descript ret:%d", ret);
        }
    }

    if (g_bleGattsCb->indicationSentCb) {
        g_bleGattsCb->indicationSentCb(param->connectId, ret);
    }
    free(ntfParam.value);
    return ret;
}


static void add_service_callback(uint8_t server_id, bt_uuid_t *uuid, uint16_t handle, errcode_t status)
{
    LOG_PRINT("[bluetooth] add service cbk: server: %d, status: %d ", server_id, status);
   // print_bt_uuid(uuid);
    g_srvc_handle = handle;   
    uint8_t swapUuid[2];
    BtUuid bt_uuid = {uuid->uuid_len, uuid->uuid};

    if (uuid->uuid_len == 2) {
        swapUuid[1] = uuid->uuid[0];
        swapUuid[0] = uuid->uuid[1];
        bt_uuid.uuid = swapUuid;
    }
    if (g_bleGattsCb->serviceAddCb) {
        g_bleGattsCb->serviceAddCb(status, server_id, &bt_uuid, handle);
    }
}

static void add_characteristic_callback(uint8_t server_id, bt_uuid_t *uuid, uint16_t service_handle,
    gatts_add_character_result_t *result, errcode_t status)
{   
    LOG_PRINT("[bluetooth] add characteristic cbk: server: %d, status: %d ", server_id, status);
    uint8_t swapUuid[2];
    BtUuid bt_uuid = {uuid->uuid_len, uuid->uuid};

    if (uuid->uuid_len == 2) {
        swapUuid[1] = uuid->uuid[0];
        swapUuid[0] = uuid->uuid[1];
        bt_uuid.uuid = swapUuid;
    }
    if (g_bleGattsCb->characteristicAddCb) {
        g_bleGattsCb->characteristicAddCb(status, server_id, &bt_uuid, service_handle, result->value_handle);
    }
}

static void add_descriptor_callback(uint8_t server_id, bt_uuid_t *uuid, uint16_t service_handle,
    uint16_t handle, errcode_t status)
{
    LOG_PRINT("[bluetooth] add descriptor cbk: server: %d, status: %d ", server_id, status);
    uint8_t swapUuid[2];
    BtUuid bt_uuid = {uuid->uuid_len, uuid->uuid};

    if (uuid->uuid_len == 2) {
        swapUuid[1] = uuid->uuid[0];
        swapUuid[0] = uuid->uuid[1];
        bt_uuid.uuid = swapUuid;
    }

    if (g_bleGattsCb->descriptorAddCb) {
        g_bleGattsCb->descriptorAddCb(status, server_id, &bt_uuid, service_handle, handle);
    }
}

static void start_service_callback(uint8_t server_id, uint16_t handle, errcode_t status)
{
    LOG_PRINT("[bluetooth] start service cbk: server: %d, status: %d ", server_id, status);
    if (g_bleGattsCb->serviceStartCb) {
        g_bleGattsCb->serviceStartCb(status, server_id, handle);
    }
}

static void stop_service_callback(uint8_t server_id, uint16_t handle, errcode_t status)
{
    LOG_PRINT("[bluetooth] stop service cbk: server: %d, status: %d ", server_id, status);
    if (g_bleGattsCb->serviceStopCb) {
        g_bleGattsCb->serviceStopCb(status, server_id, handle);
    }
}

static void delete_service_callback(uint8_t server_id, errcode_t status)
{
    LOG_PRINT("[bluetooth] delete service cbk: server: %d, status: %d ", server_id, status);
    if (g_bleGattsCb->serviceDeleteCb) {
        g_bleGattsCb->serviceDeleteCb(status, server_id, g_deleteServiceHandle);
    }
}

static void read_request_callback(uint8_t server_id, uint16_t conn_id, gatts_req_read_cb_t *read_cb_para,
    errcode_t status)
{   
    LOG_PRINT("[bluetooth] read request cbk: server: %d, status: %d ", server_id, status);
    BtReqReadCbPara para = {0};
    BdAddr addrBuff = {0};
    para.bdAddr = &addrBuff;
    memcpy_s(para.bdAddr, sizeof(BdAddr), &g_bdAddr, sizeof(BdAddr));
    para.connId = conn_id;
    para.transId = OHOS_BT_TRANSPORT_LE;
    para.attrHandle = read_cb_para->handle;
    para.offset = read_cb_para->offset;
    para.isLong = read_cb_para->is_long;
    g_serverRequestId = read_cb_para->request_id;
    if (g_bleGattsCb->requestReadCb) {
        g_bleGattsCb->requestReadCb(para);
    }
    
    if(g_srvc_func_read) {
        uint8_t arr[] = {0x0,0x3,0x4,0x0};
        unsigned int len = 4;
        g_srvc_func_read(&arr,&len);
    }
}

static void write_request_callback(uint8_t server_id, uint16_t conn_id, gatts_req_write_cb_t *write_cb_para,
    errcode_t status)
{   
    LOG_PRINT("[bluetooth] write request cbk: server: %d, status: %d ", server_id, status);
    BtReqWriteCbPara para;
    BdAddr addrBuff = {0};
    para.bdAddr = &addrBuff;
    memcpy_s(para.bdAddr, sizeof(BdAddr), &g_bdAddr, sizeof(BdAddr));
    g_serverRequestId = write_cb_para->request_id;
    
    if (write_cb_para->is_prep) {
        GattsSendRspParam rsp = {0};
        char one_byte_rsp = 0;
        rsp.connectId   = conn_id;
        rsp.status      = OHOS_GATT_SUCCESS;
        rsp.attrHandle  = write_cb_para->handle;
        rsp.valueLen    = sizeof(one_byte_rsp);
        rsp.value       = &one_byte_rsp;
        int ret = BleGattsSendResponse(g_server_id, &rsp);
        if (ret != ERRCODE_BT_SUCCESS) {
            HILOG_DEBUG("[bluetooth] BleGattsSendResponse ret:%d", ret);
        }
    }

    para.connId = conn_id;
    para.transId = OHOS_BT_TRANSPORT_LE;
    para.attrHandle = write_cb_para->handle;
    para.offset = write_cb_para->offset;
    para.length = write_cb_para->length;
    para.needRsp = write_cb_para->need_rsp;
    para.isPrep = write_cb_para->is_prep;
    para.value = write_cb_para->value;
    g_serverRequestId = write_cb_para->request_id;
    if (g_bleGattsCb->requestWriteCb) {
        g_bleGattsCb->requestWriteCb(para);
    }
    if (g_srvc_func_write) {
        int ret = g_srvc_func_write(write_cb_para->value,write_cb_para->length);
        if (ret != ERRCODE_BT_SUCCESS) {
            HILOG_DEBUG("[bluetooth] g_srvc_func_write ret:%d", ret);
        }
    }
}

static void mtu_changed_callback(uint8_t server_id, uint16_t conn_id, uint16_t mtu_size, errcode_t status)
{
    LOG_PRINT("[bluetooth] mtu changed cbk: server: %d, status: %d ", server_id, status);
    if (g_bleGattsCb->mtuChangeCb) {
        g_bleGattsCb->mtuChangeCb(conn_id, mtu_size);
    }
}

static gatts_callbacks_t g_gattCallback = {
    .add_service_cb          = add_service_callback,
    .add_characteristic_cb   = add_characteristic_callback,
    .add_descriptor_cb       = add_descriptor_callback,
    .start_service_cb        = start_service_callback,
    .stop_service_cb         = stop_service_callback,
    .delete_service_cb       = delete_service_callback,
    .read_request_cb         = read_request_callback,
    .write_request_cb        = write_request_callback,
    .mtu_changed_cb          = mtu_changed_callback,
};

int BleGattsRegisterCallbacks(BtGattServerCallbacks *func)
{   
    HILOG_DEBUG("[bluetooth] BleGattsRegisterCallbacks ");
    if (func == NULL) {
        HILOG_ERROR("[bluetooth] BleGattsRegisterCallbacks func is NULL");
        return -1;
    }
    g_bleGattsCb = func;
    return gatts_register_callbacks(&g_gattCallback);
}

int BleGattsDisconnect(int serverId, BdAddr bdAddr, int connId)
{
    HILOG_DEBUG("[bluetooth] BleGattsDisconnect ");
    bd_addr_t bd_addr = { 0 };
    bd_addr.type = BT_ADDRESS_TYPE_PUBLIC_DEVICE_ADDRESS;
    memcpy_s(bd_addr.addr, BD_ADDR_LEN, bdAddr.addr, BD_ADDR_LEN);
    return gap_ble_disconnect_remote_device(&bd_addr);
}
